function varargout = genSrcCode(modelName, varargin)
%GENSRCCODE 从Simulink模型生成源代码
%   此函数使用Embedded Coder从指定的Simulink模型生成C/C++源代码。
%   支持顶层模型和模型引用两种代码生成模式。
%
%语法:
%   genSrcCode(modelName)
%   genSrcCode(modelName, 'TreatAsTopMdl')
%   result = genSrcCode(modelName)
%   result = genSrcCode(modelName, 'TreatAsTopMdl')
%
%输入参数:
%   modelName - Simulink模型名称（字符串）
%
%可选参数:
%   'TreatAsTopMdl' - 将模型作为顶层模型处理，生成完整的应用程序代码
%                     如果不指定此参数，则作为模型引用处理
%
%输出参数:
%   result - 结构体（可选），包含代码生成结果信息
%            .Message - 代码生成结果消息
%
%说明:
%   - 首先检查Embedded Coder许可证是否可用
%   - 关闭所有当前打开的模型以避免冲突
%   - 验证模型启动脚本是否存在
%   - 切换到项目工作目录并清理临时文件
%   - 执行模型初始化脚本
%   - 根据参数选择代码生成模式：
%     * 无额外参数：模型引用代码生成
%     * 'TreatAsTopMdl'：顶层模型代码生成
%   - 生成完成后自动关闭模型
%
%代码生成模式:
%   顶层模型模式：生成完整的应用程序代码，包括main函数
%   模型引用模式：仅生成模型引用的代码，用于被其他模型调用
%
%先决条件:
%   - 需要Embedded Coder许可证
%   - 模型启动脚本 'open_[ModelName].m' 必须存在
%   - 模型必须正确配置代码生成设置
%
%工作环境:
%   函数会自动切换到项目工作目录，并清理可能存在的slprj文件夹
%
%错误处理:
%   - 许可证不可用时抛出错误
%   - 启动脚本不存在时抛出错误
%   - 代码生成失败时slbuild会抛出相应错误
%
%依赖项:
%   dig.isProductInstalled - 检查产品安装状态
%   bdclose - 关闭Simulink模型
%   ProjectPathManager.getDirPath - 获取项目目录路径
%   slbuild - Simulink代码生成函数
%   evalin - 在工作空间执行代码
%   close_system - 关闭Simulink系统
%
%参见:
%   slbuild, Simulink.fileGenControl, bdclose, close_system



if ~dig.isProductInstalled('Embedded Coder')
    error('An Embedded Coder license is not available.');
end

% Close all models.
bdclose('all');

% Check for prerequisites.
if ~exist(['open_', modelName], 'file')
    error(['Model startup script ''open_', modelName, ''' not found.']);
end

% Change directory to the work folder.
cd(ProjectPathManager.getDirPath('work'));

% Remove left over slprj folder in the work folder.
items = dir(pwd);
itemNames = {items.name};
if any(strcmp('slprj', itemNames))
    rmdir('slprj', 's');
end

% Open the model.
disp(['Opening Simulink model ', modelName, '.']);
evalin('base', ['open_', modelName]);

% Generate code.
if nargin > 1
    codeType = 'Top model';
    slbuild(modelName);
else
    codeType = 'Model reference';
    slbuild(modelName, 'ModelReferenceCoderTargetOnly');
end

% Close the model.
disp(['Closing Simulink model ', modelName, '.']);
close_system(modelName, 0);

result.Message = [codeType, ' code for ', modelName, ' is successfully generated.'];
if nargout > 0
    varargout{1} = result;
end
disp(result.Message);

end
